﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using BenevolentSunData;

namespace BenevolentSun
{
    public class TextMenu
    {

        List<TextField> entries = new List<TextField>();
        public List<TextField> Entries
        {
            get { return entries; }
        }

        public void AddEntry(TextField entry)
        {
            if (IsAnimating)
                throw (new Exception("Cannot modify the menu entries while it is animating!"));
            entries.Add(entry);
        }

        public void RemoveEntry(TextField entry)
        {
            if (IsAnimating)
                throw (new Exception("Cannot modify the menu entries while it is animating!"));
            entries.Remove(entry);
            if (selectedIndex > entries.Count - 1)
                selectedIndex--;
        }


        List<Tween> xTweens = new List<Tween>();
        List<Tween> yTweens = new List<Tween>();


        protected int selectedIndex = -1;
        public int SelectedIndex
        {
            get { return selectedIndex; }
        }

        public TextField Selected
        {
            get
            {
                if (selectedIndex != -1)
                {
                    return entries[selectedIndex];
                }
                else
                {
                    return null;
                }
            }
        }

        public Boolean IsAnimating
        {
            get { return xTweens.Count != 0 && yTweens.Count != 0; }
        }


        public Color? SelectedColor = null;

        public Color? UnselectedColor = null;


        public virtual void Update(GameTime gameTime)
        {
            if (selectedIndex == -1 && entries.Count > 0)
                selectedIndex = 0;

            List<Tween> tweensToUpdate = new List<Tween>(xTweens);
            foreach (Tween tween in tweensToUpdate)
            {
                // Update Tween
                tween.Update(gameTime);

                ((TextField)(tween.Object)).Position.X = tween.Value;

                // If Finished remove it
                if (tween.IsFinished)
                {
                    xTweens.Remove(tween);
                }
            }

            tweensToUpdate = new List<Tween>(yTweens);
            foreach (Tween tween in tweensToUpdate)
            {
                // Update Tween
                tween.Update(gameTime);

                ((TextField)(tween.Object)).Position.Y = tween.Value;

                // If Finished remove it
                if (tween.IsFinished)
                {
                    yTweens.Remove(tween);
                }
            }
        }


        public virtual void Draw(SpriteBatch spriteBatch)
        {
            int index = 0;
            foreach (TextField entry in entries)
            {
                if (index == selectedIndex && SelectedColor != null)
                {
                    entry.Color = (Color)SelectedColor;
                }
                if (index != selectedIndex && UnselectedColor != null)
                {
                    entry.Color = (Color)UnselectedColor;
                }

                entry.Draw(spriteBatch);

                index++;
            }
        }


        /// <summary>
        /// Causes the menu to animate each entry to a given position that is dictated by its index in the entry set and the parameters provided.
        /// </summary>
        /// <param name="basePosition">The root position of the menu, this is the start of the menu, where entry 0 will be positioned.</param>
        /// <param name="spacing">Specifies the desired space between each menu entry.</param>
        /// <param name="seconds">Amount of time each entry will take to tween.</param>
        /// <param name="tweenSpacing">Amount of time between each entry tween starting.</param>
        public void AnimatePositions(Vector2 basePosition, Vector2 spacing, double seconds, double tweenSpacing)
        {
            xTweens.Clear();
            yTweens.Clear();
            float index = 0f;
            foreach (TextField entry in entries)
            {
                Tween xTween = new Tween(entry.Position.X, basePosition.X + spacing.X * index, tweenSpacing * index, seconds, Tween.LoopType.None, entry);
                Tween yTween = new Tween(entry.Position.Y, basePosition.Y + spacing.Y * index, tweenSpacing * index, seconds, Tween.LoopType.None, entry);

                xTweens.Add(xTween);
                yTweens.Add(yTween);

                index++;
            }
        }

        /// <summary>
        /// Causes the menu to set each entry to a given position that is dictated by its index in the entry set and the parameters provided.
        /// </summary>
        /// <param name="basePosition">The root position of the menu, this is the top left of the menu, where entry 0 will be.</param>
        /// <param name="spacing">Specifies the desired space between each menu entry.</param>
        public void SetPositions(Vector2 basePosition, Vector2 spacing)
        {
            xTweens.Clear();
            yTweens.Clear();
            float index = 0f;
            foreach (TextField entry in entries)
            {
                entry.Position = basePosition + spacing * index;

                index++;
            }
        }

        public void DistributeX(float left, float right)
        {
            /*
            xTweens.Clear();
            yTweens.Clear();
            float index = 0f;
            float spacing = (right - left) / (entries.Count - 1);
            foreach (TextField entry in entries)
            {
                entry.Position = new Vector2(left + spacing * index, entry.Position.Y);

                index++;
            }
            */

            xTweens.Clear();
            yTweens.Clear();
            float index = 0f;


            float totalSpace = right - left;
            foreach (TextField entry in entries)
            {
                //entry.TextDimensions.

                totalSpace -= entry.TextDimensions.X;
            }

            float spacing = (totalSpace) / (entries.Count - 1);
            float running = 0;
            foreach (TextField entry in entries)
            {

                float bonus = 0;
                if (entry.AlignH == AlignH.Center)
                    bonus = entry.TextDimensions.X / 2f;
                else if (entry.AlignH == AlignH.Right)
                    bonus = entry.TextDimensions.X;

                entry.Position = new Vector2(bonus + running + left + spacing * index, entry.Position.Y);

                running += entry.TextDimensions.X;

                index++;
            }
        }

        /// <summary>
        /// Stops animating.  Advances to the end if parameter is set otherwise they are stopped in place.
        /// </summary>
        public void StopAnimating(bool advanceToEnd)
        {
            if (advanceToEnd)
            {
                foreach (Tween tween in xTweens)
                {
                    // Update Tween
                    tween.AdvanceToEnd();

                    ((TextField)(tween.Object)).Position.X = tween.Value;
                }

                foreach (Tween tween in yTweens)
                {
                    // Update Tween
                    tween.AdvanceToEnd();

                    ((TextField)(tween.Object)).Position.Y = tween.Value;
                }
            }

            xTweens.Clear();
            yTweens.Clear();
        }


        public Boolean Next()
        {
            return Next(false);
        }

        public virtual Boolean Next(bool rollover)
        {
            if (entries.Count == 0)
                return false;

            selectedIndex++;
            if (selectedIndex == entries.Count)
            {
                if (rollover)
                {
                    selectedIndex = 0;
                    return true;
                }
                else
                {
                    selectedIndex = entries.Count - 1;
                    return false;
                }
            }
            return true;
        }


        public Boolean Prev()
        {
            return Prev(false);
        }

        public virtual Boolean Prev(bool rollover)
        {
            if (entries.Count == 0)
                return false;

            selectedIndex--;
            if (selectedIndex < 0)
            {
                if (rollover)
                {
                    selectedIndex = entries.Count - 1;
                    return true;
                }
                else
                {
                    selectedIndex = 0;
                    return false;
                }
            }
            return true;
        }

    }
}
